package com.mxprojects.views
{
	import com.mxprojects.constructors.ButtonLarge;
	import com.mxprojects.constructors.CheckboxConstructor;
	import com.mxprojects.constructors.Divider;
	import com.mxprojects.constructors.InputConstructor;
	import com.mxprojects.constructors.SimpleTextField;
	import com.mxprojects.gui.BreadCrumbs;
	import com.mxprojects.gui.DefaultDialog;
	import com.mxprojects.gui.PageNav;
	import com.mxprojects.gui.Resizer;
	import com.mxprojects.gui.Styles;
	import com.mxprojects.gui.ThreadItem;
	import com.mxprojects.io.BoardCookie;
	import com.mxprojects.io.Config;
	import com.mxprojects.io.CustomEvent;
	import com.mxprojects.io.DeepLinking;
	import com.mxprojects.io.ServerHandler;
	import com.mxprojects.io.Utils;
	import com.mxprojects.language.Language;
	import com.mxprojects.language.Word;
	
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	import flash.text.TextFieldAutoSize;
	
	public class Search extends Threads
	{		
		private static const LABEL_CSS:String = "searchLabel";
		private static const INPUT_CSS:String = "searchInput";
		private static const INCLUDE_WORD:String = "<span class=\"searchHelpKeywords\">+ </span>";		
		private static const OMIT_WORD:String = "<span class=\"searchHelpKeywords\">- </span>";		
		private static const PARTIAL_WORD:String = "<span class=\"searchHelpKeywords\">* </span>";		
		
		public static var forumData:Object;
		public static var searchData:Object;
		
		private static var holder:Sprite;
		private static var keyword:InputConstructor;
		private static var username:InputConstructor;
		private static var searchLocation:SimpleTextField;
		private static var searchButton:ButtonLarge;
		private static var forumsToSearch:Array;
		private static var locationsToSearch:Array;
		private static var serverHandler:ServerHandler = new ServerHandler();
		private static var resultsVisible:Boolean = false;
		private static var largestLabelWidth:int = 0;
		private static var topicsCheck:CheckboxConstructor;
		private static var postsCheck:CheckboxConstructor;
		private static var dataToSend:Object;
		private static var sectionTitle:SimpleTextField;
		private static var baseX:int; //used after the inputs are built
		
		public function Search(){}
		
		public static function load():void {
			//place the stuff on the stage that needs to happen
			setupStage();
			
			//clear out the previous forum IDs and search locations
			forumsToSearch = new Array();
			locationsToSearch = new Array();
			searchData = null;
			
			//create a holder to hold all of the stuff
			holder = new Sprite();
			
			//make sure we have the list of categories, otherwise go get 'em
			if(Forums.forumData != null){
				forumData = Forums.forumData;
				setupUI();
			}else{
				Forums.load(true, setupUI);
			}
			
//			holder.graphics.beginFill(0xffcc00, .3);
//			holder.graphics.drawRect(0,0,holder.width,holder.height);
//			holder.graphics.endFill();
		}
		
		public static function search(page:int = 1, keywords:String = "", author:String = "", searchType:String = "t", isQuickSearch:Boolean = false):void {			
			//check to see if the catData has been loaded, if not throw them to the main search page
			if(forumData == null){
				DeepLinking.setLink(Word.SEARCH, DeepLinking.createLinkArray(0));
				return;
			}
			
			//clear stuff
			setupStage();
			
			//send the search off
			dataToSend = new Object();
			
			if(keyword != null){
				dataToSend.keywords = keyword.getValue();
				dataToSend.author = username.getValue();
				if(postsCheck.getValueIfChecked() != ""){
					searchType = "p";
				}
			}else{
				dataToSend.keywords = keywords;
				dataToSend.author = author;
			}
			
			//check if the page nav is sending the keywords!
			if(keywords != ""){
				dataToSend.keywords = keywords;
			}
			if(author != ""){
				dataToSend.author = author;
			}
			
			if(searchType != "p" && searchType != "t"){
				searchType = "t";
			}
			dataToSend.type = searchType;
			
			if(forumsToSearch == null){
				dataToSend.forumsToSearch = "";
			}else{
				dataToSend.forumsToSearch = forumsToSearch.toString();
				if(forumData["forumCount"] == forumsToSearch.length){
					//if all the forums are selected then remove them all
					dataToSend.forumsToSearch = "";
				}	
			}
			
			//send the amount of search results returned, same as the threads per page
			dataToSend.threadsPerPage = Config.THREADS_PER_PAGE;
			dataToSend.pagesToCache = Config.SEARCH_PAGES_TO_CACHE;
			dataToSend.page = page;
			
			//if they are logged in let's see what they can search
			dataToSend.guestGroupID = Config.GUEST_GROUP_ID;
			if(BoardCookie.getUserID() != null){
				dataToSend.flashUserID = BoardCookie.getUserID();
			}
			
			//see if we've got enough data or if we gotta go get some more
			if(searchData != null && !isQuickSearch){
				//check if we've got enough threads
				var maxSearch:int = page * Config.THREADS_PER_PAGE - 1;
				if(searchData["search"+maxSearch+"topic"] != undefined){
					searchData.currentPage = page;
					showResults();
					return;
				}
			}
						
			serverHandler.transmitData("search.php", dataToSend);
			serverHandler.listenForData(showResults);
		}

		private static function showResults(event:CustomEvent = null):void {		
			//see what we've got shall we?
			if(event != null){
				searchData = event.getServerData();
			}
			
			var nextY:int = 0;
			
			//rebuild the breadcrumbs
			BreadCrumbs.createCrumbs(0, "", 0, "", Word.SEARCH, Language.main(Word.SEARCH) + ": " + Utils.numberFormat(Number(searchData.totalThreadsFound)) + " " + Language.main(Word.THREADS));
			DeepLinking.setTitle(Language.main(Word.SEARCH) + ": " + searchData.totalThreadsFound + " " + Language.main(Word.THREADS));
			
			//if there is something to show
			if(searchData.totalResults > 0){
				//setup the page nav
				PageNav.createNav(searchData.currentPage, searchData.totalPages, -1, dataToSend.keywords, dataToSend.author, dataToSend.type);
				
				//put the thread header up
				threadHeader.y = nextY;
				nextY += threadHeader.height - Config.DEFAULT_LINE_HEIGHT;
				MXP3.addContent(threadHeader);
				
				//loop through the threads
				for(var i:uint = (searchData.currentPage - 1) * Config.THREADS_PER_PAGE; i < searchData.currentPage * Config.THREADS_PER_PAGE; i++){
					
					if(searchData["search"+i+"topic"] != undefined){
						var thread:ThreadItem = new ThreadItem(searchData["search"+i+"topic"],
																searchData["search"+i+"author"],
																searchData["search"+i+"authorID"],
																searchData["search"+i+"replies"],
																searchData["search"+i+"views"],
																searchData["search"+i+"lastPost"],
																searchData["search"+i+"lastPoster"],
																threadHeader);
						
						thread.y = nextY;
						thread.name = "search" + i;
						thread.threadID = searchData["search"+i+"threadID"];
						nextY += thread.height - Config.DEFAULT_LINE_HEIGHT;
						MXP3.addContent(thread);
					}else{
						break;
					}
				}
				
				//put the footer on
				threadFooter.y = nextY;
				threadFooter.resize();
				nextY += threadFooter.height - Config.DEFAULT_LINE_HEIGHT;
				MXP3.addContent(threadFooter);
				
				//visible results
				resultsVisible = true;
				
				//resize the page if we need to
				Resizer.resizeContent();
			}else{
				//if we don't have any results display a message to let them know, and reload the search below it
				DefaultDialog.show(Language.main(Word.ERROR_NO_SEARCH_RESULTS));
				
				//load the default search area
				if(!DeepLinking.goBack()){
					//if we are local make sure we go back
					DeepLinking.setLink(Word.SEARCH, DeepLinking.createLinkArray());
				}
			}
		}
		
		public static function resize():void {
			//move the stuff around
			if(resultsVisible){
				threadHeader.resize();
				threadFooter.resize();
				
				//handle the thread items
				for(var i:uint = (searchData.currentPage - 1) * Config.THREADS_PER_PAGE; i < searchData.currentPage * Config.THREADS_PER_PAGE; i++){
					var thread:ThreadItem = MXP3.getContent("search"+i);
					if(thread != null){
						thread.resize();
					}else{
						break;
					}
				}
			}
		}
		
		private static function setupUI(event:CustomEvent = null):void {
			//if the event was loaded we need to setup catData
			if(event != null){
				forumData = event.getServerData();
				Forums.forumData = forumData;
			}
			
			//put a title on
			var searchText:String = "<span class=\"searchTitle\">" + Language.main(Word.ADVANCED_SEARCH) + "</span>";
			if(sectionTitle == null){
				sectionTitle = new SimpleTextField(searchText);
				sectionTitle.x = Styles.css.getStyle(".searchTitle").x;
				sectionTitle.y = Styles.css.getStyle(".searchTitle").y;
			}else{
				sectionTitle.htmlText = searchText;
			}
			
			MXP3.addContent(sectionTitle);
			
			holder.y = sectionTitle.y + sectionTitle.height + Config.TEXT_PADDING;
			holder.x = sectionTitle.x;
			
			//build out the search inputs
			buildInputs();
			
			//ask where they would like to search
			buildSearchLocations();
			
			//a little note about selecting forums
			buildForumInfoBox();
			
			//build the forum selector
			buildForumSelector();
			
			//show the different search options
			buildHelpBox();
			
			//at it to the stage
			MXP3.addContent(holder);
			
			//put on the search button after everything is built
			createDividerAndButton();
			
			//no results yet
			resultsVisible = false;
			
			//resize the page if we need to
			Resizer.resizeContent();
		}
		
		private static function checkSearch(event:MouseEvent):void {
			//this will determine if the search actually fires or if we throw an error
			if(keyword.getValue() != "" || username.getValue() != ""){
				var searchLocation:String = "t";
				if(postsCheck.getValueIfChecked() != ""){
					searchLocation = "p";
				}
				
				var linkArray:Array = DeepLinking.createLinkArray(-1, 1, keyword.getValue(), username.getValue(), searchLocation);
				DeepLinking.setLink(Word.SEARCH, linkArray);
			}else{
				//show an error about needing to search for something
				DefaultDialog.show(Language.main(Word.ERROR_EMPTY_SEARCH));
			}
		}
		
		private static function setupStage():void {
			//since we need to clear and reset things twice, let's make a function!
			MXP3.clearBoard();
			
			//tell the board where we are
			MXP3.currentLocation = Word.SEARCH;
			PageNav.clearNav();
			BreadCrumbs.createCrumbs(0, "", 0, "", Word.SEARCH, Language.main(Word.SEARCH));
			DeepLinking.setTitle(Language.main(Word.SEARCH));
		}	
			
		private static function buildInputs():void {
			//this will add the KEYWORDS and AUTHOR input boxes to search
			keyword = new InputConstructor(Language.main(Word.KEYWORDS), "", 1 + 100, false, 1, LABEL_CSS, INPUT_CSS);
			username = new InputConstructor(Language.main(Word.USERNAME), "", 2 + 100, false, 1, LABEL_CSS, INPUT_CSS);
			searchLocation = new SimpleTextField("<span class=\"formInputLabel\">" + Language.main(Word.SEARCH_LOCATION) + InputConstructor.LABEL_SEPARATOR + "</span>");
			
			//see which label is the largest
			if(keyword.inputLabel.width > largestLabelWidth){
				largestLabelWidth = keyword.inputLabel.width;
			}
			
			if(username.inputLabel.width > largestLabelWidth){
				largestLabelWidth = username.inputLabel.width;
			}
			
			if(searchLocation.width > largestLabelWidth){
				largestLabelWidth = searchLocation.width;
			}
			
			//move the elements to where they need to go
			keyword.x += largestLabelWidth - keyword.inputLabel.width;
			username.x += largestLabelWidth - username.inputLabel.width;
			searchLocation.x += largestLabelWidth - searchLocation.width;
			
			username.y = keyword.y + keyword.height + Config.TEXT_PADDING/2;
			searchLocation.y = username.y + username.height + Config.TEXT_PADDING;
			
			//setup the baseX
			baseX = keyword.x + keyword.inputBox.x;
			
			//add them to the holder
			holder.addChild(keyword);
			holder.addChild(username);
			holder.addChild(searchLocation);
		}
		
		private static function buildSearchLocations():void {
			//setup the co-ords
			var nextX:int = baseX;
			
			//create the checkboxes
			topicsCheck = new CheckboxConstructor(Language.main(Word.TOPICS), Word.TRUE, true);
			topicsCheck.x = nextX;
			topicsCheck.y = Math.round(searchLocation.y + searchLocation.height/2 - topicsCheck.height/2);
			nextX += topicsCheck.width + Config.TEXT_PADDING;
			holder.addChild(topicsCheck);
			
			postsCheck = new CheckboxConstructor(Language.main(Word.POSTS), Word.TRUE);
			postsCheck.x = nextX;
			postsCheck.y = topicsCheck.y;
			holder.addChild(postsCheck);
			
			//add the topics and posts to the areas that can be searched (only 1 at a time though)
			locationsToSearch.push(topicsCheck);
			locationsToSearch.push(postsCheck);
			
			//add listeners to the topics and post so that only 1 can be checked at a time
			if(!topicsCheck.hasEventListener(CheckboxConstructor.TOGGLE)){
				topicsCheck.addEventListener(CheckboxConstructor.TOGGLE, toggleSearchLocation, false, 0, true);
				postsCheck.addEventListener(CheckboxConstructor.TOGGLE, toggleSearchLocation, false, 0, true);
			}
		}
		
		private static function buildHelpBox():void {
			//this is just a text block that tells users what to do with searches
			var helpText:String = "<span class=\"searchHelp\">";
				helpText += "<span class=\"searchHelpTitle\">" + Language.main(Word.SEARCH_TIPS) + InputConstructor.LABEL_SEPARATOR + "</span><br><br>";
				helpText += INCLUDE_WORD + Language.main(Word.WORDS_TO_INCLUDE) + "<br>";
				helpText += OMIT_WORD + Language.main(Word.WORDS_TO_OMIT) + "<br>";
				helpText += PARTIAL_WORD + Language.main(Word.PARTIAL_WORDS) + "<br><br>";
				helpText += "<span class=\"searchHelpKeywords\">\""+Language.main(Word.PHRASES_IN_QUOTES)+"\" </span>" + Language.main(Word.WORDS_IN_QUOTES);
			helpText += "</span>";
			var searchHelp:SimpleTextField = new SimpleTextField("", 2, false, int(Styles.css.getStyle(".searchHelp")["width"]));
			searchHelp.x = keyword.x + keyword.width + Config.COLUMN_PADDING;
			searchHelp.y = keyword.y;
			searchHelp.autoSize = TextFieldAutoSize.CENTER;
			searchHelp.htmlText = helpText;
			
			holder.addChild(searchHelp);
		}
		
		private static function buildForumInfoBox():void {
			//this just puts a little note about the searching of the forums
			var nextY:int = holder.height + Config.TEXT_PADDING;
			
			//add a divider
			var divider:Divider = new Divider(1,0xffcc00);
			Styles.setProperties(divider, ".searchDivider");
			divider.x = baseX;
			divider.y = nextY;
			divider.width = keyword.inputBox.width;
			nextY += divider.height + Config.TEXT_PADDING/2;
			holder.addChild(divider);
			
			//add the note
			var searchNote:SimpleTextField = new SimpleTextField("", 2, false, divider.width);
			searchNote.x = baseX - 2; //again the stupid leading here
			searchNote.y = nextY;
			searchNote.autoSize = TextFieldAutoSize.CENTER;
			searchNote.htmlText = "<span class=\"searchForumNote\">" + Language.main(Word.FORUM_NOTE) + "</span>";
			holder.addChild(searchNote);
		}
		
		private static function buildForumSelector():void {
			//this will add the area to choose which forums to search
			var nextY:int = holder.height;
			var nextX:int = baseX;
			var startY:int = nextY; //this is for the column split to know where to start again
			var totalCategories:int = int(forumData["categoryCount"]);
			var columnSplitPoint:int = Math.ceil(totalCategories / Config.SEARCH_CATEGORY_COLUMNS);
			var splitter:int = columnSplitPoint;
			var largestWidth:int = 0;
			
			//loop through the categories and forums
			for(var i:int = 0; i < totalCategories; i++){
				if(i == splitter){
					//leftColumnBottomY = nextY + Config.TEXT_PADDING;
					nextY = startY;
					nextX += largestWidth + Config.COLUMN_PADDING;
					largestWidth = 0;
					
					//set the next split point
					splitter += columnSplitPoint;
				}
				
				var category:SimpleTextField = new SimpleTextField("<span class=\"searchCategories\">" + forumData["category" + i + "title"] + "</span>");
				var categoryWidth:int = category.width;
				category.x = nextX - 2; //pretty sure this is some sort of default leading that I can't control
				category.y = nextY + Config.TEXT_PADDING;
				nextY += category.height + Config.TEXT_PADDING;
				holder.addChild(category);
				
				//see if the category is the largest thing
				if(categoryWidth > largestWidth){
					largestWidth = categoryWidth;
				}
				
				//any forums belong to these titles?
				for(var j:int = 0; j < forumData["forumCount"]; j++){
					if(forumData["category" + i + "ID"] == forumData["forum" + j + "categoryID"]){
						var forumSelect:CheckboxConstructor = new CheckboxConstructor(forumData["forum" + j + "title"], forumData["forum" + j + "forumID"]);
						var forumWidth:int = forumSelect.width;
						forumSelect.x = nextX;
						forumSelect.y = nextY;
						nextY += Math.floor(forumSelect.height + Config.TEXT_PADDING/2);
						
						//see if the checkbox is the largest thing
						if(forumWidth > largestWidth){
							largestWidth = forumWidth;
						}
						
						//listen for the toggles
						forumSelect.addEventListener(CheckboxConstructor.TOGGLE, toggleForum, false, 0, true);
						
						holder.addChild(forumSelect);
					}
				}
			}
		}

		private static function createDividerAndButton():void {			
			//add a divider
			var divider:Divider = new Divider(1, 0xffcc00);
			Styles.setProperties(divider, ".searchDivider");
			divider.x = baseX;
			divider.y = Math.round(holder.height + Config.TEXT_PADDING*2);
			divider.width = Math.round(holder.width - baseX);
			holder.addChild(divider);
			
			//put a search button on the stage
			searchButton = new ButtonLarge(Language.main(Word.SEARCH), checkSearch);
			searchButton.y = Math.round(holder.y + holder.height + Config.TEXT_PADDING * 2);
			searchButton.x = holder.x + baseX;
			
			MXP3.addContent(searchButton);
		}
				
		private static function toggleForum(event:CustomEvent):void {
			//this will add and remove the forums from the array
			var isChecked:Boolean = event.customParameter[0];
			var forumID:int = event.customParameter[1];
			
			if(isChecked){
				//add the ID to the forums to search
				forumsToSearch.push(forumID);
			}else{
				//find the ID and remove it
				forumsToSearch.splice(forumsToSearch.indexOf(forumID), 1);
			}
		}
		
		private static function toggleSearchLocation(event:CustomEvent):void {
			//if one gets checked (or is already checked) make sure the other one get's un-checked
			var checkBox:CheckboxConstructor = event.target as CheckboxConstructor;
			var isChecked:Boolean = event.customParameter[0];
			
			//if it came in being toggled from false to true, then set the others to false
			if(isChecked){
				//loop through the array of locations and set the others to false
				for(var i:int = 0; i < locationsToSearch.length; i++){
					var otherBox:CheckboxConstructor = locationsToSearch[i] as CheckboxConstructor;
					if(otherBox != checkBox){
						otherBox.setCheckState(false);
					}
				}
			}else{
				//if it was already checked and was clicked again, force it to being checked
				checkBox.setCheckState(true);
			}
		}
	}
}